import pygtk
pygtk.require('2.0')
import gtk
import sound
import typing
import os

TYPING_ROOT = os.path.dirname(os.path.abspath(__file__))
while(os.path.isfile(TYPING_ROOT)):
    TYPING_ROOT = os.path.dirname(TYPING_ROOT)
IMAGE_SOURCE = TYPING_ROOT + os.sep + "images" + os.sep

class FreeMode(gtk.EventBox):

    #Initialize a window for Free Mode
    def __init__(self,window):
        super(FreeMode, self).__init__()
        self.win = window

        #Start out as though the user had just typed "a"
        self.displayLetter = "a"

        #Sets up the ability to play sound, and the events to do so on key-presses
        self.connect("key-press-event", self.keypresssound)
        
        #Setup a VBox to display the other elements above one another.       
        self.displayTable = gtk.Table(10, 10, True)
        self.add(self.displayTable)
        self.displayTable.set_row_spacings(10)
        self.displayTable.set_col_spacings(10)
        self.displayTable.show()        
        
        #Load up the reactive display elements        
        panel = self.response_panel()
        self.displayTable.attach(panel, 0, 10, 0, 4)
        panel.show()
        
        #Load up back button        
        backbutton = gtk.Button()
        image = gtk.Image()
        image.set_from_file(IMAGE_SOURCE + os.sep + "backbutton.gif")
        image.show()
        backbutton.set_image(image)
        backbutton.show() 
        self.displayTable.attach(backbutton, 0, 1, 4, 5)
        backbutton.connect("clicked", lambda w: gtk.main_quit()) 

        #Load up the keyboard        
        self.keyboard = typing.Typing(self)# ,lambda w: gtk.main_quit())
        self.displayTable.attach(self.keyboard, 0, 10, 5, 10)
        self.keyboard.show()

        #Set up the ability to change the letter displayed based on what is pressed        
        self.updateLetterListener = self.connect("key-press-event", self.update_character)
        
        #Set up so that killing the window will correctly send up a set of deletes and quits.
        self.deleter = self.win.connect("delete_event", self.delete_event)
        self.quit = False    

    #-------------------------------------------------------
    #SOUND
    #Determines if there is a sound for the key just pressed
    #Using the same trigger to change image
    #and, if so, plays it
    def keypresssound(self, widget, event):
        print "key pressed %s, 2!" % event.keyval
        if (event.keyval <= 122 and event.keyval >= 97): # or (event.keyval <= 90 and event.keyval >=65):
            self.displayLetter = event.string

            soundPlay = sound.Sound()
            soundPlay.setSound(TYPING_ROOT + os.sep + "sounds" + os.sep + event.string)
            soundPlay.run()

            #Update image
            self.image.hide()
            self.showImage(event.string)
    #-------------------------------------------------------

    #Shows an image associated with a given letter out to the user.
    def showImage(self, imageName):
        try:
            file_check = file(TYPING_ROOT + os.sep + "images" + os.sep + "freeMode" + os.sep + imageName + ".gif")
        except IOError, error:
            return False
        pixbuf = self.image.get_pixbuf()
        pixbuf = gtk.gdk.pixbuf_new_from_file(IMAGE_SOURCE + os.sep + "freeMode" + os.sep + imageName + ".gif").scale_simple(200, 200, gtk.gdk.INTERP_BILINEAR)
        self.image.set_from_pixbuf(pixbuf)
        self.image.show()

    #Sets up the textbuffer to be able to dynamically display letters, including with size 48 font
    #Should also eventually add the panel to display an image for each letter
    def response_panel(self):
        panel = gtk.Table(4, 10, True)
        panel.set_row_spacings(20)
        panel.set_col_spacings(20)
        
        #Loads up starting images (letter "a"), and displays
        self.image = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file(IMAGE_SOURCE + os.sep + "freeMode" + os.sep + "a.gif").scale_simple(200, 200, gtk.gdk.INTERP_BILINEAR)
        self.image.set_from_pixbuf(pixbuf)
        self.imagebutton = gtk.Button()
        self.imagebutton.set_image(self.image)
        panel.attach(self.imagebutton, 0, 4, 0, 4)
        self.imagebutton.connect("clicked", self.play_imageword_sound)
        self.image.show()
        self.imagebutton.show()

        #Build image buffers, so we can display the appropriate upper/lowercase letters on keypress.
        self.dict_upperpixbuf = {}
        self.dict_lowerpixbuf = {}
        alphastring = "abcdefghijklmnopqrstuvwxyz"
        filename_prefix = IMAGE_SOURCE + os.sep + "keyboard" + os.sep + "am_"

        #Load the images in for faster response later.        
        for i in range(len(alphastring)):
            letter = alphastring[i]
            self.dict_upperpixbuf[letter] = gtk.gdk.pixbuf_new_from_file(filename_prefix + letter + "01.gif").scale_simple(60, 100, gtk.gdk.INTERP_BILINEAR)
            self.dict_lowerpixbuf[letter] = gtk.gdk.pixbuf_new_from_file(filename_prefix + letter + "02.gif").scale_simple(60, 100, gtk.gdk.INTERP_BILINEAR)

        #Create buttons to store the upper/lower case letters        
        self.upperbutton = gtk.Button()
        self.upperimage = gtk.Image()
        self.upperimage.set_from_pixbuf(self.dict_upperpixbuf["a"])
        self.upperbutton.set_image(self.upperimage)
        panel.attach(self.upperbutton, 4, 7, 0, 4)
        self.upperbutton.connect("clicked", self.play_male_sound)
        self.upperimage.show()
        self.upperbutton.show()
        
        self.lowerbutton = gtk.Button()
        self.lowerimage = gtk.Image()
        self.lowerimage.set_from_pixbuf(self.dict_lowerpixbuf["a"])
        self.lowerbutton.set_image(self.lowerimage)
        panel.attach(self.lowerbutton, 7, 10, 0, 4)
        self.lowerbutton.connect("clicked", self.play_female_sound)
        self.lowerimage.show()
        self.lowerbutton.show()
        
        return panel  
    
    def update_character(self, widget, event):
        #Update the upper/lowercase letter being shown
        if (event.keyval <= 122 and event.keyval >= 97):
            upperimage = self.upperbutton.get_image()
            upperimage.set_from_pixbuf(self.dict_upperpixbuf[event.string])
            self.upperbutton.set_image(upperimage)
            self.upperbutton.show()
            
            lowerimage = self.lowerbutton.get_image()
            lowerimage.set_from_pixbuf(self.dict_lowerpixbuf[event.string])
            self.lowerbutton.set_image(lowerimage)
            self.lowerbutton.show()
            
        return True

    #Plays the sound of the letter spoken by a male, when the upper-case letter is pressed
    def play_male_sound(self, widget):
        print "playing male"
        soundPlay = sound.Sound()
        soundPlay.setSound(TYPING_ROOT + os.sep + "sounds" + os.sep + "formal male" + os.sep + self.displayLetter)
        soundPlay.run()
        return True

    #Plays the sound of the letter spoken by a female, when the lower-case letter is pressed    
    def play_female_sound(self, widget):
        print "playing female"
        soundPlay = sound.Sound()
        soundPlay.setSound(TYPING_ROOT + os.sep + "sounds" + os.sep + "formal female" + os.sep + self.displayLetter)
        soundPlay.run()
        return True

    #Plays the sound of the image displayed, when it is pressed    
    def play_imageword_sound(self, widget):
        print "playing image word %s" %self.displayLetter
        soundPlay = sound.Sound()
        soundPlay.setSound(TYPING_ROOT + os.sep + "sounds" + os.sep + "image words" + os.sep + self.displayLetter)
        soundPlay.run()
        return True
        
    #Delets the window, and sets quit to true, indicating we are trying to end the program
    def delete_event(self, widget, event, data=None):
        print "Freemode Quitting"
        self.quit = True
        gtk.main_quit()
        return False

    #Waits around while the user presses keys.
    #If they hit the X button for the window, self.quit will be false before
    #Calling gtk.main_quit(), and we will return true.  Otherwise, we will
    #disconnect the deleter trigger here (to allow the higher level one to
    #work correctly unblocked)
    def runGame(self):
        #Focus event attention so it starts on this widget and works its way up
        self.grab_add()
        gtk.main()
        #Release event attention from this widget.
        self.grab_remove()
        if(not self.quit):
            self.win.disconnect(self.deleter)
        return self.quit

def main():
	gtk.main()
	return 0
